package com.hmdp.interceptor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hmdp.dto.UserDTO;
import com.hmdp.entity.User;
import com.hmdp.utils.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.hmdp.utils.RedisConstants.LOGIN_USER_KEY;
import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user;


//拦截需要登录的资源
public class LoginInterceptor implements HandlerInterceptor {

    private StringRedisTemplate stringRedisTemplate;

    //map序列化器
    private ObjectMapper objectMapper;

    public LoginInterceptor(StringRedisTemplate stringRedisTemplate,ObjectMapper objectMapper)
    {
        this.stringRedisTemplate = stringRedisTemplate;
        this.objectMapper = objectMapper;
    }


    //基于session的登录拦截
    /*@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取session
        HttpSession session = request.getSession();
        //判断用户是否存在
        Object user = session.getAttribute("user");

         //不存在表示未登录，拦截需要登录的资源
        if(user==null){
            response.setStatus(401);
            return false;
        }

        //保存已经的登录用户
        UserHolder.saveUser((UserDTO) user);

        return true;
    }*/

    //基于redis的登录拦截（不用刷新策略）
    /*@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取请求头的token不是key （key是LOGIN_USER_KEY + token ）
        String token = request.getHeader("authorization");  //前端设置的后缀key
        //判断key是否为空，为空表示前端未传token来
        if(StrUtil.isBlank(token)){
            response.setStatus(401);
            return false;
        }
        //从redis获取token的map集合，判断map集合是否为空
        String key = LOGIN_USER_KEY + token;  //真正的key
        Map<Object, Object> map = stringRedisTemplate.opsForHash().entries(key);
        //如果map为空，用户未登录
        if(map.isEmpty()){
            response.setStatus(401);
            return false;
        }

        //反序列化为原始类型
        map.forEach((key2, value) -> {
                    try {
                        //反序列化为map集合
                        Object originalValue = objectMapper.readValue((String) value, Object.class);  // 反序列化
                        map.put(key2, originalValue); //覆盖原来序列化的字符串（value）
                    } catch (JsonProcessingException e) {
                        e.printStackTrace();
                    }
        });

       // 将map集合转为userdto对象 注意不是maptobean
//            Object id = map.get("id");
//            map.replace("id",id,Long.parseLong((String) id)); //不通用

        UserDTO userDTO = BeanUtil.fillBeanWithMap(map,new UserDTO(),false);
        //保存用户
        UserHolder.saveUser(userDTO);
        //重新设置有效期30分钟
        stringRedisTemplate.expire(key,30, TimeUnit.MINUTES);
        return true;

        //判断用户是否已经登录
        /*if(UserHolder.getUser()==null){
            response.setStatus(401);
            return false;
        }
        return true;/*
    }*/

    //拦截需要登录的请求（双重拦截）
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断用户是否已经登录
        if(UserHolder.getUser()==null){
            response.setStatus(401);
            return false;
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}
